import Camera from './camera';
import Scene from './scene';

import { mat4, vec3, vec2 } from 'gl-matrix';

export default class ViewControls {
    scene: Scene;
    camera: Camera;
    element: HTMLElement;
    movementSpeed: number;
    rotationSpeed: number;

    constructor(scene: Scene, element: HTMLElement) {
        this.scene = scene;
        this.camera = scene.camera;
        this.element = element;
        this.movementSpeed = 1.25;
        this.rotationSpeed = 0.01;
        this.setupEventListeners();
    }

    private setupEventListeners(): void {
        this.element.addEventListener('keydown', (event) => this.handleKeyDown(event));
        this.element.addEventListener('mousemove', (event) => this.handleMouseMove(event));
        // 确保 canvas 获得焦点
        this.element.addEventListener('click', () => this.element.focus()); 
        this.element.addEventListener('wheel', (event) => this.handleWheel(event), { passive: true }); 
    }

    private handleKeyDown(event: KeyboardEvent): void {
        const [x, y, z] = this.camera.position;

        switch (event.key) {
            case 'a':
                this.camera.setPosition(x - this.movementSpeed, y, z);
                break;
            case 'd':
                this.camera.setPosition(x + this.movementSpeed, y, z);
                break;
            case 'w':
                this.camera.setPosition(x, y + this.movementSpeed, z);
                break;
            case 's':
                this.camera.setPosition(x, y - this.movementSpeed, z);
                break;
            default:
                break;
        }

        // 同步相机参数到Scene中
        this.scene.updateCamera();
        console.log('Camera updated:', this.camera.position, this.camera.rotation);
    }

    angle: number = 0;

    directX: vec3 = vec3.fromValues(1, 0, 0);
    directY: vec3 = vec3.fromValues(0, 1, 0);
    directZ: vec3 = vec3.fromValues(0, 0, 1);

    private handleWheel(event: WheelEvent): void {

        // 获取目标位置
        const targetPos = this.camera.targetPosition;
        const pos = this.camera.position;

        // 根据鼠标移动调整距离
        let distance = vec3.distance(pos, targetPos);
        distance -= event.deltaY * 0.02 * this.movementSpeed;

        this.zoom(pos, targetPos, distance);

        // 同步相机参数到 Scene 中
        this.scene.updateCamera();

    }

    directLast: vec3 = vec3.fromValues(0, 0, -1);
    zoom(pos: vec3, targetPos: vec3, distance: number) {
        let direct = vec3.fromValues(0, 0, -1);
        if (vec3.length(this.directLast) > 0.1) {
            direct = this.directLast;
        }
        if (distance > 0.1) {
            direct = vec3.sub(direct, pos, targetPos);
            direct = vec3.normalize(direct, direct);
        }

        vec3.scale(direct, direct, distance);

        let newPos = vec3.add(vec3.create(), targetPos, direct);
        this.camera.setPosition(newPos[0], newPos[1], newPos[2]);

        vec3.sub(newPos, newPos, pos);
        vec3.add(newPos, targetPos, newPos);
        this.camera.setTargetPosition(newPos[0], newPos[1], newPos[2]);
    }

    private handleMouseMove(event: MouseEvent): void {

        // 获取目标位置
        const targetPos = this.camera.targetPosition;
        const pos = this.camera.position;

        if (event.buttons === 1) { // 左键按下
            // 根据鼠标移动调整水平角度
            this.angle -= event.movementX * this.rotationSpeed;
            const radius = vec2.distance([pos[0], pos[2]], [targetPos[0], targetPos[2]]);
            // 计算新的相机位置
            let newCameraX = targetPos[0] + radius * Math.sin(this.angle);
            let newCameraY = pos[1] + event.movementY * this.movementSpeed;
            let newCameraZ = targetPos[2] + radius * Math.cos(this.angle);

            // 更新相机位置
            this.camera.setPosition(newCameraX, newCameraY, newCameraZ);
        }
        else if (event.buttons === 4) { // 中键
            // 根据鼠标移动调整距离
            let distance = vec3.distance(pos, targetPos);
            distance -= event.movementY * this.movementSpeed;

            this.zoom(pos, targetPos, distance);
        }
        else if (event.buttons === 2) { // 右键
            // 根据鼠标移动调整距离
            let distance = vec3.distance(pos, targetPos);
            let direct = vec3.fromValues(0, 0, -1);
            if (vec3.length(this.directLast) > 0.1) {
                direct = this.directLast;
            }
            if (distance > 0.1) {
                direct = vec3.sub(direct, pos, targetPos);
                direct = vec3.normalize(direct, direct);
            }

            let right = vec3.cross(vec3.create(), direct, this.directY);
            if (vec3.dot(direct, this.directY) > 0.99) {
                if (vec3.dot(direct, this.directX) < 0.99) {
                    right = vec3.cross(vec3.create(), direct, this.directX);
                }
                else {
                    right = vec3.cross(vec3.create(), direct, this.directZ);
                }
            }

            right = vec3.normalize(right, right);

            let up = vec3.cross(vec3.create(), right, direct);
            up = vec3.normalize(up, up);

            let newTargetMoveV = vec3.scale(vec3.create(), up, event.movementY * this.movementSpeed);
            let newTargetMoveH = vec3.scale(vec3.create(), right, event.movementX * this.movementSpeed);

            let newTargetMove = vec3.add(vec3.create(), newTargetMoveV, newTargetMoveH);

            let newPos = vec3.add(vec3.create(), pos, newTargetMove);

            this.camera.setPosition(newPos[0], newPos[1], newPos[2]);
            let newTargetPos = vec3.add(vec3.create(), targetPos, newTargetMove);

            this.camera.setTargetPosition(newTargetPos[0], newTargetPos[1], newTargetPos[2]);
        }

        // 同步相机参数到 Scene 中
        this.scene.updateCamera();
    }
}
